www.gusucode.com > php框架系统:MDPHP麦迪源码 v1.xPHP源码程序 > php框架系统:MDPHP麦迪源码 v1.x/mdphp_v1.0.beta/mdphp_v1.0.beta/Library/Model/public.php
<?php /** * 麦迪模型类 * @author: 麦迪科技 <i@md8.cc> * @link: http://soft.md8.cc * @version: 1.3 */ namespace MDPHP; import('$->Library->Model->Db->interface'); final class Model{ public $name, $connection, $opt, $data; private $obj; /** * 模型实例化 * @param string $name 表名 * @param array $connection 模型配置项 */ public function __construct($name=null, $connection){ //初始化驱动 $driver = strtolower($connection['TYPE']); $className = 'MDPHP\Db' . ucfirst($driver); import('$->Library->Model->Db->' . $driver); //建立驱动对象 $this->obj = new $className($connection); //错误处理 if(is_array($this->obj->error)) error($this->obj->error['id'], $this->obj->error['title'], $this->obj->error['content']); //初始类成员属性 $this->connection = $connection; $this->opt = array( 'pri' => null, //主键 'field' => '*', //查询键组 'fieldData' => array(), //字段组 'where' => '', 'group' => '', 'having' => '', 'order' => '', 'limit' => '', 'join' => '' ); //设置当前表 $this->table($name); } /** * 执行SQL * @param string $sql * @return [type] 成功返回资源标识符, 失败返回False. */ public function query($sql){ $result = $this->obj->query($sql); Custom::log(array('sql'=>$sql, 'result'=>($result ? 'True' : 'False')), 'Q'); return $result; } /** * 设置查询条件 * @param [type] $opt 条件(可为字符串、数组) * @return Model类 * * -- 以下测试表索引为`id` -- * * 索引查询: where(1) * `id`=1 * 多索引查询(OR): where(array(1, 2, 3, 4, 5)) * `id`=1 and `id`=2 and `id`=3 and `id`=4 and `id`=5 * * 键名查询: where(array('name'=>'xhao')) * `name`="xhao" * 键名+条件: where(array('name'=>array('xhao', 'sxyz', array('or')))) * `name`="xhao" or `name`="sxyz" * 键名+条件: where(array('name'=>array('xhao', 'sxyz', array('!=', 'and')))) * `name`<>"xhao" and `name`<>"sxyz" * * 数组展开: where(array('id'=>array(1, 2, array(3, 4), 5, array('<>')))) * `id`<>1 or `id`<>2 or `id`<>3 or `id`<>4 or `id`<>5 * * In: where(array('id'=>array(array(1, 2, 3, 4), 5, 6, array('in')))) * `id` in (1,2,3,4,5,6) * Not in: where(array('id'=>array(array(1, 2, 3, 4), 5, 6, array('not in')))) * `id` not in (1,2,3,4,5,6) * Between: where(array('id'=>array(1, 100, array('between')))) * `id` between 1 and 100 * Not between: where(array('id'=>array(1, 100, array('not between')))) * `id` not between 1 and 100 * Like: where(array('name'=>array('xhao', array('like')))) * `name` like "xhao" * Not like: where(array('name'=>array('xhao', array('not like')))) * `name` not like "xhao" * * Or: where(array('name'=>array('xhao', 'sxyz', array('<>', 'or')))) * `name`<>"xhao" or `name`<>"sxyz" * And: where(array('name'=>array('xhao', 'sxyz', array('<>', 'and')))) * `name`<>"xhao" and `name`<>"sxyz" * */ public function where($opt, $logic='and'){ //初始化 $where = ''; $this->opt['where'] = ''; if(is_numeric($opt)){ //主键方式 $where = $this->opt['pri'] . '=' . $opt; }elseif(is_string($opt)){ //SQL查询 $where = $opt; }elseif(is_object($opt)){ //转换为数组 $opt = get_object_vars($opt); } if(is_array($opt)){ //查询语句 list($sentence[0], $sentence[1]) = array( array('IN', 'OR', 'AND', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'LIKE', 'NOT LIKE'), array('=', '>', '<', '<>', '==', '!=') ); //多主键模式 foreach($opt as $key => $value){ if(is_numeric($key) && is_numeric($value)){ $where .= $this->opt['pri'] . '=' . $value . ' ' . $logic . ' '; }else{ $where = ''; break; } } if($where) goto end; //遍历循环 foreach($opt as $key => $value){ //解析键名 $key = self::parseField($key); //多字段 if(is_array($value)){ //高级配置 if(isset($value[count($value)-1]) && is_array(end($value))){ $adv = end($value); if(count($adv)>0 && (in_array_case($adv[0], $sentence[0]) || in_array($adv[0], $sentence[1]))) array_pop($value); else unset($adv); } //符号 $sign = in_array($adv[0], $sentence[1]) ? str_replace(array('==', '!='), array('=', '<>'), $adv[0]) : '='; //类型 $type = (isset($adv)) ? trim(strtolower(end($adv))) : 'and'; //展开数组 foreach($value as $k => $v){ if(is_array($v)) array_splice($value, $k, 1, array_values($v)); } //IN - NOT IN if(in_array($type, array('in', 'not in'))){ $where .= $key . ' ' . $type . ' (' . implode(',', array_map(function($v){ return $this->obj->escapeString($v); }, $value)) . ')'; } //BETWEEN - NOT BETWEEN if(in_array($type, array('between', 'not between'))){ $where .= $key . ' ' . $type . ' ' . $this->obj->escapeString(isset($value[0]) ? $value[0] : '') . ' ' . $logic . ' ' . $this->obj->escapeString(isset($value[1]) ? $value[1] : ''); } //LIKE - NOT LIKE if(in_array($type, array('like', 'not like'))){ $where .= $key . ' ' . $type . ' ' . $this->obj->escapeString(isset($value[0]) ? $value[0] : ''); } //AND - OR if(in_array($type, array('and', 'or'))){ foreach($value as $value){ $where .= $key . $sign . $this->obj->escapeString($value) . ' ' . $type . ' '; } $where = trim_right($where, ' ' . $type . ' '); } $where .= ' ' . $logic . ' '; }else{ //普通模式 $where .= $key . '=' . $this->obj->escapeString($value) . ' ' . $logic . ' '; } } } end: $this->opt['where'] = preg_replace('/^\s*(or|and|xor)\s*/i', '', $where); //首部清理 $this->opt['where'] = preg_replace('/\s*(or|and|xor)\s*$/i', '', $this->opt['where']); //尾部清理 $this->opt['where'] = ' where ' . $this->opt['where']; return $this; } /** * 设置查询字段 * @param string $rule 预设值的字段(可为字符串、数组 为字符串时以","分割 字段不加"`") * @param string $auto 自动补全前缀 * @return Model类 * * 设置别名: * field('article.*,class.id as classID', true) * field(array('article.*', 'class.id as classID'), true) * */ public function field($rule='*', $auto=false){ if(!is_array($rule)) $rule = explode(',', $rule); $str = null; foreach($rule as $key => $value){ $value = str_replace(' AS ', ' as ', $value); if(strpos($value, ' as ')===false){ $value = self::parseField(($auto ? $this->connection['PREFIX'] : '') . $value); }else{ $array = explode(' as ', $value); $value = self::parseField(($auto ? $this->connection['PREFIX'] : '') . $array[0]) . ' as ' . self::parseField($array[1]); } $str .= $value . ','; } $this->opt['field'] = rtrim($str, ','); return $this; } /** * 设置排序 * @param string $name 字段名 * @param string $by 排序方式: asc 或 desc * @return Model类 */ public function order($name, $by='asc'){ $this->opt['order'] = ' order by ' . ($name ? self::parseField($name).' ' : '') . $by; return $this; } /** * 设置截取 * 2个参数全填写: 参数1为开始位置(从0开始), 参数2为截取数量(<1 则使用1); * 只填写参数1: 限制数量(可用于删除表项), <1则使用1填充; * @param integer $param1 参数1 * @param integer $param2 参数2 * @return Model类 */ public function limit($param1=0, $param2=1){ if(func_num_args() > 1) $this->opt['limit'] = ' limit ' . intval($param1) . ',' . intval($param2<1 ? 1 : $param2); else $this->opt['limit'] = ' limit ' . intval($param1<1 ? 1 : $param1); return $this; } /** * 列出一条记录 * @return array */ public function find(){ if(!$this->obj->result) $this->query('select ' . $this->opt['field'] . ' from ' . ($this->opt['join'] ? $this->opt['join'] : self::parseField($this->name)) . $this->opt['where'] . $this->opt['order'] . $this->opt['limit']); return $this->obj->fetch(); } /** * 列出所有记录 * @return array */ public function select(){ if(!$this->obj->result) $this->query('select ' . $this->opt['field'] . ' from ' . ($this->opt['join'] ? $this->opt['join'] : self::parseField($this->name)) . $this->opt['where'] . $this->opt['order'] . $this->opt['limit']); $array = array(); while($row = $this->obj->fetch(false)){ $array[] = $row; } $this->obj->fetch(); //回收 return $array; } /** * 统计表项数量 * @param string $field 表名, 为空则使用field()方法所设置值 * @return integer 表项数量 */ public function count($field=null){ if($field === null) $field = $this->opt['field']; $this->query('select count(' . $field . ') as `MDPHP` from ' . ($this->opt['join'] ? $this->opt['join'] : self::parseField($this->name)) . $this->opt['where']); $result = $this->find(); return is_array($result) ? $result['MDPHP'] : $result; } /** * 欲提交数据设置 * @param array $data 被设置的数据, 为空使用POST数据. * @return Model类 */ public function data($data=null){ if(empty($data)) $data = $_POST; if(get_magic_quotes_gpc()){ foreach($data as $key => $value){ $data[$key] = stripslashes($value); } } $this->data = $data; return $this; } /** * 添加表项 * @param array $data 可为空, 为空则使用data()方法所设置数据. * @return [type] 添加失败返回False, 成功返回主键ID(如无主键则返回0). */ public function add($data=null){ if(!empty($data)) $this->data($data); $keys = null; $values = null; foreach($this->data as $k => $v){ $keys .= self::parseField($k) . ','; $values .= $this->obj->escapeString($v) . ','; } $this->optInit(); if($this->query('insert into ' . self::parseField($this->name) . '(' . rtrim($keys, ',') . ') values (' . rtrim($values, ',') . ')')) return $this->obj->getInsertId(); else return false; } /** * 修改表项 * @param array $data 可为空, 为空则使用data()方法所设置数据. * @param integer $pri 可空, 若提供主键, 则被优先使用. * @return [type] 执行失败返回False, 成功返回修改行数. */ public function save($data=null, $pri=0){ if(!empty($data)) $this->data($data); if($pri && func_num_args()>1) $where = ' where ' . $this->opt['pri'] . '=' . intval($pri); else $where = $this->opt['where']; $str = null; foreach($this->data as $key => $value){ $str .= self::parseField($key) . '=' . $this->obj->escapeString($value) . ','; } $this->query('update ' . self::parseField($this->name) . ' set ' . rtrim($str, ',') . $where . $this->opt['order'] . $this->opt['limit']); $this->optInit(); if($this->obj->result) return $this->obj->getAffectedRows(); else return false; } /** * 删除表项 * @param integer $pri 可空, 若提供主键, 则被优先使用. * @return [type] 执行失败返回False, 成功返回删除行数. */ public function del($pri=0){ if($pri && func_num_args()>0) $where = ' where ' . $this->opt['pri'] . '=' . intval($pri); else $where = $this->opt['where']; $this->query('delete from ' . ($this->opt['join'] ? $this->opt['join'] : self::parseField($this->name)) . $where . $this->opt['order'] . $this->opt['limit']); if($this->obj->result) return $this->obj->getAffectedRows(); else return false; } /** * 关联查询 * @param string $left 左表, 为空删除关联 * @param string $right 右表 * @param string $where 条件语句 * @param string $type 关联类型 * @return Model类 * * join('article', 'class', array('article.class'=>'class.id')) * `md_article` inner join `md_class` on `md_article`.`class`=`md_class`.`id` * */ public function join($left='', $right='', $where, $type='inner join'){ if(func_num_args()<2 && !$left) $this->opt['join'] = ''; if(is_array($where)){ $str = ''; foreach($where as $key => $value){ $str .= self::parseField($this->connection['PREFIX'].$key) . '=' . self::parseField($this->connection['PREFIX'].$value) . ' and '; } $str = trim_right($str, ' and '); }else{ $str = $where; } $this->opt['join'] = self::parseField($this->connection['PREFIX'].$left) . ' ' . $type . ' ' . self::parseField($this->connection['PREFIX'].$right) . ' on ' . $str; return $this; } /** * 设置表 * @param string $name * @return Model类 */ public function table($name){ $this->name = $this->connection['PREFIX'] . $name; //设置类成员属性 $this->getAllField(); $this->getPrimaryKey(); return $this; } /** * 获取数据表结构并缓存 * @return array */ public function getAllField(){ $this->query('show columns from ' . self::parseField($this->name)); $result = $this->select(); foreach($result as $value){ $fieldData = array(); $fieldData['field'] = $value['Field']; $fieldData['type'] = $value['Type']; $fieldData['null'] = $value['Null']; $fieldData['key'] = strtoupper($value['Key']) == 'PRI'; $fieldData['default'] = $value['Default']; $fieldData['extra'] = $value['Extra']; $this->opt['fieldData'][$fieldData['field']] = $fieldData; } } /** * 获得表主键字段 * @return string 字段名 */ public function getPrimaryKey(){ foreach($this->opt['fieldData'] as $value){ if($value['key']){ $this->opt['pri'] = self::parseField($value['field']); break; } } } /** * 字段代码解析 * @param string $str * @return string 处理后代码 */ static function parseField($str){ $array=explode('.', $str); $str=''; foreach($array as $value){ $str .= ($value=='*' ? '*' : ('`'.str_replace('`', '\`', trim($value)).'`.')); } return rtrim($str, '.'); } /** * 配置信息还原 */ private function optInit($opt=false){ if($opt){ $this->opt = array( 'field' => '*', 'where' => '', 'group' => '', 'having' => '', 'order' => '', 'limit' => '', 'join' => '' ); } $this->data = null; return $this; } }